-- recup main addon object
if not BLTRCD then return end
local BLTRCD = BLTRCD

-- library loading
local LGIST = LibStub("LibGroupInSpecT-1.0")
local AceDB = LibStub("AceDB-3.0")
local CB = LibStub("LibCandyBar-3.0")
local Elv = IsAddOnLoaded("ElvUI")

-- "global" var
local freeBackgrounds = {}
local debug_lvl=0

local function debugPrint(msg, lvl)
	if (debug_lvl >= lvl) then
		print(msg)
	end
end

if (Elv) then
	E, L, V, P, G =  unpack(ElvUI);
end

BLTRCD.categories = {}
BLTRCD.raid = {}

function BLTRCD.GetPartyType()
    return (
		(select(2, IsInInstance()) == "pvp" and "battleground")
		or (select(2, IsInInstance()) == "arena" and "battleground")
		or (IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and "lfr")
		or (IsInRaid() and "raid")
		or (IsInGroup() and "party")
		or "none"
	)
end

function BLTRCD.UpdateCD(cd) 
	local nbAvailable=0
	local nb=0
	for _,cdRoster in pairs(cd.roster) do
		nb=nb+1
		if cdRoster.up and not cdRoster.dead then
			nbAvailable=nbAvailable+1
		end
	end
	cd.nbCD=nb
	cd.nbUP=nbAvailable
	cd.frameicon.text:SetText(cd.nbUP)
end

local function barSorter(a, b)
	return a.remaining < b.remaining and true or false
end

local cdSorter = {
	class = function(a,b)
		return a.cooldown.class < b.cooldown.class and true or false
	end,
	cooldown = function(a,b)
		return a.cooldown.CD < b.cooldown.CD and true or false
	end,
	name = function(a,b)
		return a.cooldown.real_name < b.cooldown.real_name and true or false
	end,
}

function BLTRCD.CDreadymode(cd)
	return
		(cd.cooldown.readymode == "yes" 
		or (cd.cooldown.readymode == "inherit" and BLTRCD.db.profile.display.category[cd.cooldown.category].readymode == "yes")
		or (cd.cooldown.readymode == "inherit" 
			and BLTRCD.db.profile.display.category[cd.cooldown.category].readymode == "inherit"
			and BLTRCD.db.profile.readymode))
end

local lastAntiSpam
local function antiSpam(time)
	if GetTime() - (lastAntiSpam or 0) > (time or 2.5) then
		lastAntiSpam = GetTime()
		return true
	else
		return false
	end
end

function BLTRCD.DisplayCD()
	local attachpoint, scale, activeX, activeY, numbarcat, bargrowth
	local tmp = {}
	local tmpCD = {}

  if antiSpam(1) then

    debugPrint("DisplayCD()",3)
    
    scale=BLTRCD.db.profile.display.scale
    activeX=BLTRCD.db.profile.display.activeX
    activeY=BLTRCD.db.profile.display.activeY
    
    for catname,cat in pairs(BLTRCD.categories) do
      if BLTRCD.db.profile.display.category[catname].enabled then
        cat.frame:Show()
      else
        cat.frame:Hide()
      end

      numbarcat=0
      
      wipe(tmpCD)
      for _,cd in pairs(cat.cdlist) do
        if cd.cooldown.enabled then
          tmpCD[#tmpCD+1]=cd
        end
      end
      
      if BLTRCD.db.profile.display.category[catname].catSorting=="inherit" then
        table.sort(tmpCD, cdSorter[BLTRCD.db.profile.display.catSorting])
      else
        table.sort(tmpCD, cdSorter[BLTRCD.db.profile.display.category[catname].catSorting])
      end
      
      for _,cd in next,tmpCD do
        BLTRCD:BLFontTemplate(cd.frameicon.text, 20*scale, 'OUTLINE')
        cd.frame:Hide()
        BLTRCD.UpdateCD(cd)
        if cd.nbCD > 0 then
          if not cd.cooldown.growth then -- should not happen, except for custom CD created before 3.1.1
            cd.cooldown.growth = "inherit"
          end
          if cd.cooldown.growth == "inherit" then
            if BLTRCD.db.profile.display.category[cd.cooldown.category].growth == "inherit" then
              bargrowth=BLTRCD.db.profile.display.growth	
            else
              bargrowth=BLTRCD.db.profile.display.category[cd.cooldown.category].growth	
            end
          else
            bargrowth=cd.cooldown.growth	
          end
          
          if (bargrowth=='LEFT') then
            attachpoint='RIGHT'
          else	
            attachpoint='LEFT'
          end
          local numbar=2
          if cd.cooldown.b_enabled == "yes" 
            or (cd.cooldown.b_enabled == "inherit" and BLTRCD.db.profile.display.category[cd.cooldown.category].b_enabled == "yes")
            or (cd.cooldown.b_enabled == "inherit" 
              and BLTRCD.db.profile.display.category[cd.cooldown.category].b_enabled == "inherit"
              and BLTRCD.db.profile.b_enabled) then

            wipe(tmp)
            for barcaster, bar in next, cd.framebars.bars do
    if not barcaster then 
      debugPrint("barcaster : NIL",2)
    end
    if not cd.roster then
      debugPrint("cd.roster: KO",2)
    end
    if not cd.roster[barcaster] then
      debugPrint("cd.roster[barcaster] : KO",2)
    end
    if cd.roster and cd.roster[barcaster] and cd.roster[barcaster].dead then
      debugPrint("cd.roster[barcaster].dead: "..tostring(cd.roster[barcaster].dead),2)
    end
              
              if cd.roster and cd.roster[barcaster] and not cd.roster[barcaster].dead then
                tmp[#tmp + 1] = bar
              end
            end
            table.sort(tmp, barSorter)
            local numbartmp=0
            for _,bar in next,tmp do  
              if numbartmp < BLTRCD.db.profile.display.nbbar then
                bar:ClearAllPoints()
                BLTRCD:BLPoint(bar, 'TOPLEFT', cd.framebars, 'TOPLEFT', 4, -4-14*numbartmp)
                bar:SetScale(scale)
                bar:Show()
                numbartmp=numbartmp+1
              else
                bar:Hide()
              end
            end
            numbar=max(numbartmp,2)
            
            BLTRCD:BLSize(cd.framebars,108*scale, (14*numbar+4)*scale)

            cd.framebars:ClearAllPoints()
            BLTRCD:BLPoint(cd.framebars,'TOP'..bargrowth, cd.frame, 'TOP'..bargrowth,0,0)
            cd.framebars:Show()
          else
            cd.framebars:Hide()
          end

          BLTRCD:BLSize(cd.frameicon,32*scale,32*scale)
          cd.frameicon:ClearAllPoints()
          BLTRCD:BLPoint(cd.frameicon,'TOP'..attachpoint, cd.frame, 'TOP'..attachpoint)
          
          BLTRCD:BLSize(cd.frame,140*scale,32*scale)
          cd.frame:ClearAllPoints()
          BLTRCD:BLPoint(cd.frame,'TOP'..attachpoint, cat.frame, 'TOP'..attachpoint, 0, -16*scale*numbarcat)

          if cd.cooldown.enabled then
            cd.frame:Show()
          end

          numbarcat = numbarcat + numbar
        end
      end
      BLTRCD:BLSize(cat.frame,140*scale,16*scale*numbarcat)
  --		BLTRCD:BLSize(cat.mover,32*scale,16*scale)
      BLTRCD:BLSize(cat.mover,140*scale,16*scale*numbarcat)
      
      BLTRCD:BLSize(BLTRCD.activeCDCat.frame,activeX,BLTRCD.db.profile.display.nbActiveCD*activeY)
      BLTRCD:BLSize(BLTRCD.activeCDCat.mover,activeX,BLTRCD.db.profile.display.nbActiveCD*activeY)
  --		BLTRCD:BLFontTemplate(BLTRCD.activeCDCat.title, activeY, 'OUTLINE')
    end
    --BLTRCD.RearrangeActiveCD()

  else
    debugPrint("DisplayCD() ANTI SPAM ACTIVATED",1)
  end

end

function BLTRCD.DisplayFrame()
	debugPrint("DisplayFrame()",3)
	if (BLTRCD.config or BLTRCD.db.profile.show == "always") then
		BLTRCD.frame:Show()
	else
		if BLTRCD.db.profile.show == "raid" and (BLTRCD.GetPartyType()=="raid" or BLTRCD.GetPartyType()=="party") then
			BLTRCD.frame:Show()
		else 
			BLTRCD.frame:Hide()
		end
	end
end

function BLTRCD:BLHeight(frame, height)
	if (Elv) then frame:Height(height) else frame:SetHeight(height) end
end
function BLTRCD:BLWidth(frame, width)
	if (Elv) then frame:Width(width) else frame:SetWidth(width) end
end
function BLTRCD:BLSize(frame, width, height)
	if (Elv) then frame:Size(width, height) else frame:SetSize(width, height) end
end
function BLTRCD:BLPoint(obj, arg1, arg2, arg3, arg4, arg5)
	if (Elv) then obj:Point(arg1, arg2, arg3, arg4, arg5) else obj:SetPoint(arg1, arg2, arg3, arg4, arg5) end
end
function BLTRCD:BLTexture()
	--if (Elv) then return E["media"].normTex else return "Interface\\AddOns\\MyAddOn\\statusbar" end
	if (Elv) then return E["media"].normTex else return "Interface\\TARGETINGFRAME\\UI-StatusBar" end
end

function BLTRCD:BLCreateBG(frame)
	if (Elv) then
		--local bg = frame.candyBarBackdrop
		local bg = nil
		if #freeBackgrounds > 0 then
			bg = tremove(freeBackgrounds)
		else
			bg = CreateFrame("Frame")
		end
		
		bg:SetTemplate("Default")
		
		bg:SetParent(frame)
		bg:ClearAllPoints()
		BLTRCD:BLPoint(bg,"TOPLEFT", frame, "TOPLEFT", -2, 2)
		BLTRCD:BLPoint(bg,"BOTTOMRIGHT", frame, "BOTTOMRIGHT", 2, -2)
		bg:SetFrameStrata("LOW")
		bg:Show()
		frame:Set("bltrcd:elvskin", bg)
	end
end

function BLTRCD:BLFontTemplate(frame, x, y)
	if(Elv) then
		frame:FontTemplate(nil, x, y)
	else
		frame:SetFont("Fonts\\FRIZQT__.TTF", x, y)
	end
end

function BLTRCD:print_r ( t )
    local print_r_cache={}
    local function sub_print_r(t,indent)
        if (print_r_cache[tostring(t)]) then
            print(indent.."*"..tostring(t))
        else
            print_r_cache[tostring(t)]=true
            if (type(t)=="table") then
                for pos,val in pairs(t) do
                    if (type(val)=="table") then
                        print(indent.."["..pos.."] => "..tostring(t).." {")
                        sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
                        print(indent..string.rep(" ",string.len(pos)+6).."}")
                    else
                        if type(pos) == "table" then
							print(indent.."[-table-] => "..tostring(val))
						else
							print(indent.."["..pos.."] => "..tostring(val))
						end
                    end
                end
            else
                print(indent..tostring(t))
            end
        end
    end
    sub_print_r(t," ")
end

function BLTRCD.ShowBackMember(name)
  debugPrint("ShowBackMember name:"..name,3)
  for _,cat in pairs(BLTRCD.categories) do
    for _,cd in pairs(cat.cdlist) do
      if cd.framebars.bars[name] then
        cd.framebars.bars[name]:Show()
      end
      if cd.roster[name] then
        cd.roster[name].dead=nil
      end
    end
  end
end

function BLTRCD.HideMemberCD(name, cd)
  if cd.roster[name] and cd.roster[name].dead then return end
  debugPrint("HideMemberCD name:"..name.." cd:"..cd.cooldown.name,4)
  local bar=cd.framebars.bars[name]
  if bar then
    bar:Hide()
  end
  if cd.roster[name] then
    cd.roster[name].dead=true
  end
end

function BLTRCD.HideMember(name)
  debugPrint("HideMember name:"..name,3)
  for _,cat in pairs(BLTRCD.categories) do
    for _,cd in pairs(cat.cdlist) do
      BLTRCD.HideMemberCD(name, cd)
    end
  end
end

function BLTRCD.RemoveMember(name)
	debugPrint("RemoveMember name:"..name,3)
	for _,cat in pairs(BLTRCD.categories) do
		for _,cd in pairs(cat.cdlist) do
			if cd.framebars.bars[name] then
				cd.framebars.bars[name]:Set("bltrcd:src_removed", true)
				cd.framebars.bars[name]:Stop()
			end
			cd.roster[name]=nil
		end
	end
end

function BLTRCD.ToggleConfigMode()
	debugPrint("ToggleConfigMode()",3)

	if (BLTRCD.config) then
		for _,cat in pairs(BLTRCD.categories) do
			cat.mover:Hide()
--			cat.frame:SetMovable(false)
		end
		
		for _, bar in next, BLTRCD.activeCDCat.bars do
			if bar:Get("bltrcd:src")=="configGuy" then
				bar:Stop()
			end
		end
		
		BLTRCD.activeCDCat.mover:Hide()
		
		BLTRCD.RemoveMember("configGuy")
		BLTRCD.config=nil
	else
		BLTRCD.activeCDCat.mover:Show()
		for _,cat in pairs(BLTRCD.categories) do
			cat.mover:Show()
--			cat.frame:SetMovable(true)			
			for _,cd in pairs(cat.cdlist) do
				cd.roster["configGuy"]={}
				cd.roster["configGuy"].up=true
				cd.roster["configGuy"].usage=0

				BLTRCD.StartCD(cd,"configGuy")
				BLTRCD.StartActiveCD(cd, "configGuy")
			end
		end
		BLTRCD.config=true
	end
	BLTRCD.DisplayCD()
	BLTRCD.RearrangeActiveCD()	
end


function BLTRCD:OnUpdate(event, guid, unit, info) 
	if not info.name then return end
	debugPrint("onUpdate event : event->"..tostring(event).."guid->"..tostring(guid).." name->"..tostring(info.name), 3)

	if BLTRCD.db.profile.filteradditionalpeople and BLTRCD.GetPartyType()=="raid" then
		unitid=LGIST:GuidToUnit(guid)
		if unitid and unitid ~= "player" then
			unitindex=unitid:sub(5,6)
			_,_,subgroup, _, _, _, _, _,_ , _, _ = GetRaidRosterInfo(unitindex)
			if GetNumGroupMembers() > 25 and subgroup > 5 then 
				BLTRCD.OnRemove(frame, event, guid)
				return
			elseif GetNumGroupMembers() < 16 and GetNumGroupMembers() > 10 and subgroup > 2 then 
			-- elseif (GetInstanceDifficulty()==4 or GetInstanceDifficulty()==6) and subgroup > 2 then -- GetInstanceDifficulty() = 4 pour 10NM et 6 pour 10HM
				BLTRCD.OnRemove(frame, event, guid)
				return
			end
		end
	end
	
	BLTRCD.raid[guid] = info.name
	for _,cat in next, BLTRCD.categories do
		for _,cd in next, cat.cdlist do
			local old_usage, old_up
			if (cd.roster[info.name]) then
				old_up = cd.roster[info.name].up
				old_usage = cd.roster[info.name].usage
				cd.roster[info.name]=nil
			end
			if (cd.cooldown.talent and info.talents and (next(info.talents) and info.talents[cd.cooldown.spellID])) or
			   (cd.cooldown.spec and info.global_spec_id and (cd.cooldown.spec == info.global_spec_id)) or 
			   (not cd.cooldown.talent and not cd.cooldown.spec and cd.cooldown.class and info.class and cd.cooldown.class == info.class) or
			   (cd.cooldown.class == "ALL") then

			   debugPrint("onUpdate : found new CD guy ", 3)
				cd.roster[info.name]={}
				cd.roster[info.name].up=old_up or true
				cd.roster[info.name].usage=old_usage or 0
				cd.roster[info.name].cd=cd.cooldown.CD or 0
				
				
				if cd.cooldown.glyphReduceCD and info.glyphs then
					local spell, modifier = unpack(cd.cooldown.glyphReduceCD)
					for spellId in next, info.glyphs do
						if spellId==spell then
							cd.roster[info.name].cd=cd.roster[info.name].cd-modifier
						end
					end
				end
				if cd.cooldown.talentReduceCD and info.glyphs then
					local spell, modifier = unpack(cd.cooldown.talentReduceCD)
					for spellId in next, info.talents do
						if spellId==spell then
							cd.roster[info.name].cd=cd.roster[info.name].cd-modifier
						end
					end
				end
				if cd.cooldown.specReduceCD and info.global_spec_id then
					local spec, modifier = unpack(cd.cooldown.specReduceCD)
					if info.global_spec_id==spec then
						cd.roster[info.name].cd=cd.roster[info.name].cd-modifier
					end
				end
				
				if BLTRCD.CDreadymode(cd) and not cd.framebars.bars[info.name] then
					BLTRCD.CreateBar(cd, info.name)
				end
				
			end
		end
	end
	BLTRCD.DisplayCD()
end

function BLTRCD.OnRemove (frame, event, guid)
	local name=BLTRCD.raid[guid]
	debugPrint("OnRemove guid:"..tostring(guid).." name:"..tostring(name),3)
	if name then 
		BLTRCD.RemoveMember(name)
	end
	BLTRCD.raid[guid]=nil
	BLTRCD.DisplayCD()
end

function BLTRCD.engageCheck()
	debugPrint("engageCheck()",3)
	if not UnitExists("boss1") then return end

	if (not BLTRCD.bossfight) then
		BLTRCD.ReinitCDUsage()
		BLTRCD.bossfight=true
		BLTRCD.pullTime=GetTime()
	else
		debugPrint("EngageCheck - LOL BLIZZ",2)
	end
end

local function checkForWipe()
	debugPrint("checkForWipe()",3)
	local w = true
	local num = GetNumGroupMembers()
	for i = 1, num do
		local name = GetRaidRosterInfo(i)
		if name then
			if UnitAffectingCombat(name) then
				w = false
			end
		end
	end
	if (w and BLTRCD.bossfight) then
		BLTRCD.bossfight=false
		BLTRCD.snapshotCDusage()
		BLTRCD.resetlongCD()
		BLTRCD:BUTTON_FIGHT_OnLoad()
    
    -- put back every member alive
    for _,cat in pairs(BLTRCD.categories) do
      for _,cd in pairs(cat.cdlist) do
        for name,cdguy in pairs(cd.roster) do
          if UnitIsConnected(name) then
            cdguy.dead = nil
          end 
        end
      end
    end
    BLTRCD.DisplayCD()
	end
	if not w then BLTRCD:ScheduleTimer(checkForWipe, 2) end
end

function BLTRCD:INSTANCE_ENCOUNTER_ENGAGE_UNIT()
	BLTRCD.engageCheck()
end

function BLTRCD:PLAYER_REGEN_ENABLED(name)
	checkForWipe()
end

function BLTRCD:PARTY_MEMBER_ENABLE(name)
  debugPrint ("PARTY_MEMBER_ENABLE "..name,1)
  BLTRCD.ShowBackMember(name)
  BLTRCD.DisplayCD()
end

function BLTRCD:PARTY_MEMBER_DISABLE(name)
  debugPrint ("PARTY_MEMBER_DISABLE "..name,1)
  BLTRCD.HideMember(name)
  BLTRCD.DisplayCD()
end

function BLTRCD:GROUP_ROSTER_UPDATE()
	BLTRCD.DisplayFrame()
end

function BLTRCD:SkinElvUI()
	local S = E:GetModule('Skins')
	BLTRCD_MAIN:StripTextures(true)
	BLTRCD_MAIN:SetTemplate()
	BLTRCD_DISPLAY:StripTextures(true)
	BLTRCD_DISPLAY:SetTemplate()
	BLTRCD_LIST:StripTextures(true)
	BLTRCD_LIST:SetTemplate()
	S:HandleButton(BLTRCD_ENGAGE)
	S:HandleButton(BLTRCD_DISENGAGE)
	S:HandleButton(BUTTON_AOE_HEAL)
	S:HandleButton(BUTTON_DEFENSIVE)
	S:HandleButton(BUTTON_GLOBAL)
	S:HandleButton(BUTTON_DPS)
	S:HandleButton(BUTTON_MANA)
	S:HandleButton(BUTTON_REZ)
	S:HandleButton(BUTTON_SINGLE_HEAL)
	S:HandleButton(BUTTON_MISC)
	S:HandleButton(BUTTON_CLOSE)
	S:HandleScrollBar(BLTRCD_SCROLLBAR)
	BLTRCD_TITLE:SetPoint("TOP", BLTRCD_MAIN, "TOP", 0, -9)
	BLTRCD_ACTIVE_NAME:SetPoint("BOTTOM", BLTRCD_DISPLAY, "BOTTOM", 0, 10)
	--BLTRCD_ENGAGE:StyleButton()
end
 
function BLTRCD:SlashProcessor_BLTRCD(input)
	local v1, v2 = input:match("^(%S*)%s*(.-)$")
	v1 = v1:lower()

	if v1 == "" then
		print("|cffc41f3bBloodlust Raidcooldowns|r: /bltrcd config - Open configuration panel")
		print("|cffc41f3bBloodlust Raidcooldowns|r: /bltrcd sim - Toggle Simulation Mode (frames unlocked)")
	elseif v1 == "report" then
		BLTRCD_MAIN:Show()
	elseif v1 == "debug" then
		debug_lvl=tonumber(v2)
		print("debug level is now "..tostring(debug_lvl))
	elseif v1 == "rescan" then
		print("Rescan raid...")
		LGIST:Rescan()
	elseif v1 == "inspect" then
		print("Inspecting "..tostring(v2).."...")
		LGIST:Refresh(v2)
	elseif v1 == "config" then
		BLTRCD.InitOptions()
	elseif v1 == "sim" then
		BLTRCD:ToggleConfigMode()
	elseif v1 == "testheal" then
    BLTRCD.ListAOEHealCD()
	elseif v1 == "testdps" then
    BLTRCD.ListAOEDPSCD()
	end
end

function BLTRCD.RearrangeActiveCD()
	debugPrint("RearrangeActiveCD()",3)
	local attachpoint
	local tmp = {}
	activeX=BLTRCD.db.profile.display.activeX
	activeY=BLTRCD.db.profile.display.activeY
	
	if (BLTRCD.db.profile.display.growth=='LEFT') then
		attachpoint='RIGHT'
	else	
		attachpoint='LEFT'
	end
	
	for _, bar in next, BLTRCD.activeCDCat.bars do
		tmp[#tmp + 1] = bar
	end
	table.sort(tmp, barSorter)

	local numbartmp=0
	for _,bar in next,tmp do 
		if numbartmp < BLTRCD.db.profile.display.nbActiveCD then
			bar:ClearAllPoints()
			BLTRCD:BLPoint(bar, 'TOP'..attachpoint, BLTRCD.activeCDCat.mover, 'TOP'..attachpoint, 0, -(activeY+4)*numbartmp)
			bar:SetWidth(activeX)
			bar:SetHeight(activeY)
			numbartmp=numbartmp+1
			bar:Show()
		else
			bar:Hide()
		end
	end
	
end

function BLTRCD.CreateActiveCDBar(cd, src)
	debugPrint("CreateActiveCDBar cd=>"..cd.cooldown.name.." src=>"..src,3)
	local bar = CB:New(BLTRCD:BLTexture(), 200, 16)
	BLTRCD.activeCDCat.bars[cd.cooldown.name..src]=bar
	bar:Set("bltrcd:type", "active")
	bar:Set("bltrcd:src", src)
	bar:Set("bltrcd:cd", cd)
	bar:SetParent(BLTRCD.activeCDCat.frame)
	bar:SetFrameStrata("MEDIUM")
	if BLTRCD.db.profile.display.backdropcolor then
		local cc=RAID_CLASS_COLORS[cd.cooldown.class] or {r=0.5; g=0.5; b=0.5}
		bar:SetColor(cc.r,cc.g,cc.b,1)
	else
		bar:SetColor(.5,.5,.5,1)
	end
	if BLTRCD.db.profile.display.baricon then
		local iconpath,_=select(3, GetSpellInfo(cd.cooldown.spellID))
		bar:SetIcon(iconpath)
	end
	bar:SetDuration(cd.cooldown.duration)
	bar:SetClampedToScreen(true)
	bar:SetScale(BLTRCD.db.profile.display.scale)
	local caster = strsplit("-",src)
	bar:SetLabel("["..cd.cooldown.category.."] "..cd.cooldown.real_name.." ("..caster..")")
	bar.candyBarLabel:SetJustifyH("LEFT")
	BLTRCD:BLCreateBG(bar)
	bar:Start()
--	BLTRCD.RearrangeActiveCD()
end

function BLTRCD.CreateBar(cd, src)
	debugPrint("CreateBar cd=>"..cd.cooldown.name.." src=>"..src,3)
	local bar = CB:New(BLTRCD:BLTexture(), 100, 10)
	cd.framebars.bars[src] = bar
	bar:Set("bltrcd:src", src)
	bar:Set("bltrcd:cd", cd)
	bar:Set("bltrcd:type", "cd")
	bar:SetParent(cd.framebars)
	bar:SetFrameStrata("MEDIUM")
	if BLTRCD.db.profile.display.backdropcolor then
		local cc=RAID_CLASS_COLORS[cd.cooldown.class] or {r=0.5; g=0.5; b=0.5}
		bar:SetColor(cc.r,cc.g,cc.b,1)
	else
		bar:SetColor(.5,.5,.5,1)
	end
	if cd.roster[src] and cd.roster[src].cd then
		bar:Set("bltrcd:dur", cd.roster[src].cd)
		bar:SetDuration(cd.roster[src].cd)
	else 
		bar:Set("bltrcd:dur", cd.cooldown.CD)
		bar:SetDuration(cd.cooldown.CD)
		debugPrint("createbar cd.roster[src].CD not set",2)
	end
	bar:SetDuration(0.05)

	bar:SetClampedToScreen(true)
	bar:SetScale(BLTRCD.db.profile.display.scale)
	local caster = strsplit("-",src)
	bar.candyBarLabel:SetJustifyH("LEFT")
	BLTRCD:BLCreateBG(bar)
	bar:SetTimeVisibility(false)
	
	if BLTRCD.CDreadymode(cd) then
--		bar:SetLabel(caster.." READY")
		bar:SetLabel(caster)
		bar:Start()
		bar.updater:Pause()
		bar:EnableMouse(true)
		bar:SetScript("OnMouseDown", function(self,event, ...) SendChatMessage("USE "..self:Get("bltrcd:cd").cooldown.real_name.." PLZ !", "WHISPER", "Common", self:Get("bltrcd:src")) end)    
	end
	
end

function BLTRCD.StartBar(cd, src)
	debugPrint("StartBar cd=>"..cd.cooldown.name.." src=>"..src,3)
	local bar=cd.framebars.bars[src]
	if not bar then
		debugPrint("Createbar again...",2)
		BLTRCD.CreateBar(cd, src)
		bar=cd.framebars.bars[src]
	end
	bar:SetLabel(src)
	bar:SetTimeVisibility(true)
	bar:SetDuration(bar:Get("bltrcd:dur"))
	if BLTRCD.CDreadymode(cd) then
		bar:EnableMouse(false)
	end
	bar:Start()
end

function BLTRCD.StartActiveCD(cd, src)
	debugPrint("StartActiveCD cd=>"..cd.cooldown.name.." src=>"..src,3)
	if cd.cooldown.duration >= 3 then
		BLTRCD.CreateActiveCDBar(cd, src)
	end
end

function BLTRCD.StartCD(cd, src)
	debugPrint("StartCD cd=>"..cd.cooldown.name.." src=>"..src,3)
	if cd.roster and cd.roster[src] then
		cd.roster[src].up=false
		if cd.roster[src].usage then
			cd.roster[src].usage = cd.roster[src].usage + 1
		else
			debugPrint("CD USAGE nil => cd:"..cd.cooldown.name.." src:"..src,2)
			cd.roster[src].usage = 1
		end

		BLTRCD.StartBar(cd, src)
	else 
	-- here we start a CD without having detected the caster is on the CD roster list
	-- either we do not have run all detections yet (slow inspects or recent reloadui/login)
	-- either we do not expect this member to cast this spellID (wrong cd definition ?)
		
		cd.roster[src]={}
		cd.roster[src].up=false
		cd.roster[src].usage=1
		
		BLTRCD.StartBar(cd, src)
	end
end

local function barstopped(event, bar)
	local type = bar:Get("bltrcd:type")
	local src = bar:Get("bltrcd:src")
	local cd = bar:Get("bltrcd:cd")
	local background = bar:Get("bltrcd:elvskin")
	local chan
	
	if type then
		debugPrint("Barstopped event type:"..type.." cd:"..cd.cooldown.name.." src:"..src,3)

		if type=="active" then
			BLTRCD.activeCDCat.bars[cd.cooldown.name..src]=nil
			BLTRCD.RearrangeActiveCD()
			
			if cd.cooldown.stopCDannounce == "inherit" then
				if BLTRCD.db.profile.display.category[cd.cooldown.category].stopCDannounce == "inherit" then
					chan = BLTRCD.db.profile.stopCDannounce
				else
					chan = BLTRCD.db.profile.display.category[cd.cooldown.category].stopCDannounce
				end
			else
				chan = cd.cooldown.stopCDannounce
			end
			BLTRCD.announce(cd.cooldown.real_name.." ("..src..") END", chan)
			
		else
			local src_removed = cd.framebars.bars[src]:Get("bltrcd:src_removed")
			cd.framebars.bars[src]=nil
			if BLTRCD.CDreadymode(cd) and not src_removed then
				BLTRCD.CreateBar(cd,src)
			end

			if cd.roster and cd.roster[src] then
				cd.roster[src].up=true
			else
				cd.roster[src]={}
				cd.roster[src].up=true
			end

			BLTRCD.DisplayCD()

			if cd.cooldown.readyCDannounce == "inherit" then
				if BLTRCD.db.profile.display.category[cd.cooldown.category].readyCDannounce == "inherit" then
					chan = BLTRCD.db.profile.readyCDannounce
				else
					chan = BLTRCD.db.profile.display.category[cd.cooldown.category].readyCDannounce
				end
			else
				chan = cd.cooldown.readyCDannounce
			end
			BLTRCD.announce(cd.cooldown.real_name.." ("..src..") READY", chan)

		end
		
		if background then
      background:ClearAllPoints()
      background:SetParent(UIParent)
      background:Hide()
      freeBackgrounds[#freeBackgrounds + 1] = background
    end

    bar:ClearAllPoints()
    bar:SetParent(UIParent)
    bar:Set("bltrcd:type", nil)
    bar:Set("bltrcd:src", nil)
    bar:Set("bltrcd:cd", nil)
    bar:Set("bltrcd:dur", nil)
    bar:Set("bltrcd:src_removed", nil)
	end
end

local count=0
function BLTRCD:OnInitialize()

	if count == 1 then return end
	
	LGIST.RegisterCallback(self, "GroupInSpecT_Update", "OnUpdate")
	LGIST.RegisterCallback(self, "GroupInSpecT_Remove", "OnRemove")

	--Thanks funkydude for his assistance on bar recycling !
	CB.RegisterCallback(self, "LibCandyBar_Stop", barstopped)

	BLTRCD:RegisterEvent("GROUP_ROSTER_UPDATE") -- TO MONITOR SOLO/PARTY/RAID CHANGE
	BLTRCD:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT")
	BLTRCD:RegisterEvent("PLAYER_REGEN_ENABLED")
--	BLTRCD:RegisterEvent("PLAYER_REGEN_DISABLED") -- DEBUG USE ONLY
  BLTRCD:RegisterEvent("PARTY_MEMBER_ENABLE")
  BLTRCD:RegisterEvent("PARTY_MEMBER_DISABLE")

	BLTRCD:RegisterChatCommand("BLTRCD", "SlashProcessor_BLTRCD")
	
	BLTRCD.db = AceDB:New("BLTRCDDB", BLTRCD.defaults, true)

	if (ElvUI and BLTRCD.db.profile.ELVUI_SKIN) then
		BLTRCD:SkinElvUI()
	end

	BLTRCD.SetupOptions()
	BLTRCD_MAIN:Hide()
	
	for cat, catprops in pairs(self.db.profile.display.category) do
		self.categories[cat]=self.CreateCatFrame(cat,catprops.enabled)
	end
	self.activeCDCat=self.CreateactiveCDCat("ActiveCD",true)

--	for i, cooldown in pairs(self.db.profile.cooldowns) do
	for i, cooldown in next, self.db.profile.cooldowns do
--		if (cooldown.enabled) then
			self.CreateCooldown(cooldown.category, i, cooldown)
--		end
	end

	count = 1
	self.DisplayCD()
	self.DisplayFrame()
end

function BLTRCD.CreateactiveCDCat(catName, isShown)
	local cat={}

	cat.frame = CreateFrame("Frame", 'BLTRaidCooldownBase_'..catName..'_Frame', BLTRCD.frame)

	cat.mover = CreateFrame("Frame", 'BLTRaidCooldownBaseMover_'..catName..'_Frame', cat.frame)
	cat.mover:SetClampedToScreen(true)

	BLTRCD:BLPoint(cat.mover,'TOPLEFT', UIParent, 'TOPLEFT', 0, 0)
	if (Elv) then
		cat.mover:SetTemplate()
--		cat.frame:SetTemplate()
	end
	cat.mover:SetMovable(true)
--	cat.mover:SetFrameStrata("HIGH")
	cat.mover:SetScript("OnDragStart", function(self) self:StartMoving() end)
	cat.mover:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
	cat.mover:EnableMouse(true)
	cat.mover:RegisterForDrag("LeftButton")
	cat.mover:Hide()

	BLTRCD:BLPoint(cat.frame,'TOPLEFT', cat.mover, 'TOPLEFT', 0, 0)
	
	-- cat.title = cat.mover:CreateFontString(nil, 'OVERLAY')
	-- BLTRCD:BLPoint(cat.title, "CENTER", cat.frame, "CENTER", 0, 0)
	-- BLTRCD:BLFontTemplate(cat.title , BLTRCD.db.profile.display.activeY, 'OUTLINE')
	-- cat.title:SetText("Active CD")
	
	if isShown then cat.frame:Show() else cat.frame:Hide() end
	
	cat.bars = {}
	cat.nbCD=0
	return cat
end

function BLTRCD.CreateCatFrame(catName, isShown)
	local cat={}

	cat.frame = CreateFrame("Frame", 'BLTRaidCooldownBase_'..catName..'_Frame', BLTRCD.frame)

	cat.mover = CreateFrame("Frame", 'BLTRaidCooldownBaseMover_'..catName..'_Frame', cat.frame)
	cat.mover:SetClampedToScreen(true)

	BLTRCD:BLPoint(cat.mover,'TOPLEFT', UIParent, 'TOPLEFT', 0, 0)
	if (Elv) then
--		cat.mover:SetTemplate()
--		cat.frame:SetTemplate()
	end
	cat.mover:SetMovable(true)
	cat.mover:SetFrameStrata("HIGH")
	cat.mover:SetScript("OnDragStart", function(self) self:StartMoving() end)
	cat.mover:SetScript("OnDragStop", 
		function(self)
			self:StopMovingOrSizing()
			local opts = BLTRCD.db.profile.display.category[catName].frameopts or {}
			local from, _, to, x, y = self:GetPoint()

			opts.anchorFrom = from
			opts.anchorTo = to
			opts.offsetx = x
			opts.offsety = y
			
			BLTRCD.db.profile.display.category[catName].frameopts = opts
		
		end)
	cat.mover:EnableMouse(true)
	cat.mover:RegisterForDrag("LeftButton")
	cat.mover:Hide()
	
	BLTRCD:BLPoint(cat.frame,'TOPLEFT', cat.mover, 'TOPLEFT', 0, 0)

	--cat.mover:SetScript("OnShow", Reset_Position)
	-- Reset saved position
	local opts = BLTRCD.db.profile.display.category[catName].frameopts
	if opts and opts.anchorTo then
		cat.mover:ClearAllPoints()
		BLTRCD:BLPoint(cat.mover, opts.anchorFrom, UIParent, opts.anchorTo, opts.offsetx, opts.offsety)
	end
	
	if isShown then cat.frame:Show() else cat.frame:Hide() end
	
	cat.cdlist = {}
	cat.nbCD=0
	return cat
end


function BLTRCD.CreateCooldown(catname, index, cooldown)
	local iconTexCoords = {.08, .92, .08, .92}
	local cd = {}

	cd.index=index
	cd.cooldown=cooldown
	cd.roster={}
	cd.nbCD=0
	cd.nbUP=0

	-- frame
	cd.frame = CreateFrame("Frame", 'BLTRaidCooldown'..index, BLTRCD.categories[catname].frame)
	cd.frame:SetClampedToScreen(true)

	-- framebars
	cd.framebars = CreateFrame("Frame", 'BLTRaidCooldownBars'..index, cd.frame)
	cd.framebars:SetClampedToScreen(true);
	cd.framebars.bars = {}

	-- icon
	cd.frameicon = CreateFrame("Button", 'BLTRaidCooldownIcon'..index, cd.frame)
	if (ElvUI) then
		cd.frameicon:SetTemplate()
--		cd.framebars:SetTemplate()
--		cd.frame:SetTemplate()
	end
	local classcolor=RAID_CLASS_COLORS[cooldown.class] or {r=0; g=0; b=0}
	cd.frameicon:SetBackdropBorderColor(classcolor.r,classcolor.g,classcolor.b)
	cd.frameicon:SetClampedToScreen(true)
	cd.frameicon.icon = cd.frameicon:CreateTexture(nil, "OVERLAY")
	cd.frameicon.icon:SetTexCoord(unpack(iconTexCoords))
	cd.frameicon.icon:SetTexture(select(3, GetSpellInfo(cooldown['spellID'])))
	BLTRCD:BLPoint(cd.frameicon.icon,'TOPLEFT', 1, -1)
	BLTRCD:BLPoint(cd.frameicon.icon,'BOTTOMRIGHT', -1, 1)
	
	-- text
	cd.frameicon.text = cd.frameicon:CreateFontString(nil, 'OVERLAY')
	BLTRCD:BLPoint(cd.frameicon.text, "CENTER", cd.frameicon, "CENTER", 0, 0)

	cd.frameicon:SetScript("OnEnter", function(self,event, ...) BLTRCD.OnEnter(self,cd) end)
	cd.frameicon:RegisterForClicks("LeftButtonDown", "RightButtonDown")
	cd.frameicon:SetScript("PostClick", function(self,event, ...) BLTRCD.PostClick(cd, event) end)    
	cd.frameicon:SetScript("OnLeave", function() BLTRCD.OnLeave() end)

	cd.frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
	cd.frame:SetScript("OnEvent", function(self,event, ...) BLTRCD.UpdateCooldown(self,event,cd,...) end)

	BLTRCD.categories[catname].cdlist[cooldown.name]=cd
	BLTRCD.categories[catname].nbCD=BLTRCD.categories[catname].nbCD+1
end

BLTRCD.bossfight=false
BLTRCD.pullTime=0
BLTRCD.lastFights={}

function BLTRCD.ReinitCDUsage()
	debugPrint("ReinitCDUsage()",2) 
	for _,cat in pairs(BLTRCD.categories) do
		for _,cd in pairs(cat.cdlist) do
			for _,cdguy in pairs(cd.roster) do
				cdguy.usage = 0
			end
		end
	end
end

function BLTRCD.snapshotCDusage()
	debugPrint("snapshotCDusage()",2) 

	lastFight={}
	lastFight.duration=GetTime()-BLTRCD.pullTime

	lastFight.categories={}
	for catname,cat in pairs(BLTRCD.categories) do
		lastFight.categories[catname] = {}
		for cdname,cd in pairs(cat.cdlist) do
			lastFight.categories[catname][cdname]={}
			lastFight.categories[catname][cdname].roster={}
			for name,cdguy in pairs(cd.roster) do
				if cd.roster[name].cd then
					lastFight.categories[catname][cdname].roster[name]={}
					lastFight.categories[catname][cdname].roster[name].value=tostring(cdguy.usage)
					lastFight.categories[catname][cdname].roster[name].maxusage=tostring((math.floor(lastFight.duration / cd.roster[name].cd)) + 1)
				else
					debugPrint("AIE catname:"..catname.." cdname:"..cdname.." cd:"..name,2)
				end
			end
		end
	end

	tinsert(BLTRCD.lastFights, 1, lastFight)
	if BLTRCD.lastFights[BLTRCD.db.profile.saveFight+1] then
		BLTRCD.lastFights[BLTRCD.db.profile.saveFight+1]=nil
	end
	debugPrint("size lastFights"..#BLTRCD.lastFights,2)
end

function BLTRCD.resetlongCD()
	-- reset all CD > 5min
	for _,cat in pairs(BLTRCD.categories) do
		for _,cd in pairs(cat.cdlist) do
			if cd.cooldown.CD >= 300 then
				for _, bar in next, cd.framebars.bars do
					bar:Stop()
				end
				for _,cdguy in pairs(cd.roster) do
					cdguy.up=true
				end
			end
		end
	end
end

function BLTRCD.ReportUsageCD(lastFight, cd)
	debugPrint("ReportUsageCD cd:"..cd.cooldown.name,2)
	
	local chan

	if (lastFight and lastFight.duration) then
		if IsLeftShiftKeyDown() then
			chan="OFFICER"
		elseif BLTRCD.GetPartyType()=="raid" then
			chan="RAID"
		else 
			chan="SAY"
		end
	
		SendChatMessage("Fight duration : "..tostring(round(lastFight.duration,2)).."s",chan)
		SendChatMessage("=== "..cd.cooldown.class.." === ".. GetSpellLink(cd.cooldown.spellID),chan)
		if lastFight.categories and lastFight.categories[cd.cooldown.category] and lastFight.categories[cd.cooldown.category][cd.cooldown.name] then
			for name,cdusage in pairs(lastFight.categories[cd.cooldown.category][cd.cooldown.name].roster) do
				SendChatMessage(name.." : "..cdusage.value.."/"..cdusage.maxusage,chan)
				debugPrint("OUTPUT ON chan "..chan.." / "..name.." : "..cdusage.value.."/"..cdusage.maxusage,2)
			end
		end
	end
end

function BLTRCD.OnEnter(self, cd)
	GameTooltip:Hide()
	GameTooltip:ClearLines()
	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT",3, 14)
	GameTooltip:AddSpellByID(cd.cooldown['spellID'])

	local cc=RAID_CLASS_COLORS[cd.cooldown.class] or {r=255; g=255; b=255}

	if not BLTRCD.bossfight and BLTRCD.lastFights[1] and BLTRCD.lastFights[1].duration then
		GameTooltip:AddDoubleLine("Last fight duration :", tostring(round(BLTRCD.lastFights[1].duration,2)).."s", 255, 255, 255, 255, 255, 255)
	end

	local cdstate, status
	for name,cdguy in pairs(cd.roster) do
    if cdguy.dead then
      cdstate="dead/disc"
    elseif cdguy.up then
      cdstate="ready"
    else
      cdstate="cd"
    end
		if BLTRCD.bossfight then
			status=tostring(cdguy.usage).." ("..cdstate..")"
		elseif BLTRCD.lastFights[1] and BLTRCD.lastFights[1].categories[cd.cooldown.category] and BLTRCD.lastFights[1].categories[cd.cooldown.category][cd.cooldown.name] and BLTRCD.lastFights[1].categories[cd.cooldown.category][cd.cooldown.name].roster and BLTRCD.lastFights[1].categories[cd.cooldown.category][cd.cooldown.name].roster[name]then
			status=tostring(BLTRCD.lastFights[1].categories[cd.cooldown.category][cd.cooldown.name].roster[name].value).."/"..BLTRCD.lastFights[1].categories[cd.cooldown.category][cd.cooldown.name].roster[name].maxusage.." ("..cdstate..")"
		else
			status=cdstate
		end
		GameTooltip:AddDoubleLine(name,status,cc.r,cc.g,cc.b,cc.r,cc.g,cc.b)
	end

	GameTooltip:Show()
end

function BLTRCD.PostClick(cd, button)
	if (button == "RightButton") then
		BLTRCD.ReportUsageCD(BLTRCD.lastFights[1], cd)
	else
		local chan
		if IsLeftShiftKeyDown() then
			chan="officer"
		else
			chan=BLTRCD.db.profile.clickCDannounce
		end
		BLTRCD.announce("----- "..cd.cooldown.real_name.." -----",chan)
		for name,cdguy in pairs(cd.roster) do
			if cdguy.up and not cdguy.dead then
				BLTRCD.announce(name.." ready !",chan)
			end
		end
	end
end

function BLTRCD.OnLeave()
	GameTooltip:Hide()
end

local function getPetOwner(pet, guid)
	if UnitGUID("pet") == guid then
		return playerName, playerGUID
	end

	local owner
	if IsInRaid() then
		for i=1, GetNumGroupMembers() do
			if UnitGUID(("raid%dpet"):format(i)) == guid then
				owner = ("raid%d"):format(i)
				break
			end
		end
	else
		for i=1, GetNumSubgroupMembers() do
			if UnitGUID(("party%dpet"):format(i)) == guid then
				owner = ("party%d"):format(i)
				break
			end
		end
	end
	if owner then
		local name, server = UnitName(owner)
		if server then name = name.."-"..server end
		return name, UnitGUID(owner)
	end
	return pet, guid
end

function BLTRCD.UpdateCooldown(self,event,cd,...)
	local group = bit.bor(COMBATLOG_OBJECT_AFFILIATION_MINE, COMBATLOG_OBJECT_AFFILIATION_PARTY, COMBATLOG_OBJECT_AFFILIATION_RAID)
	if (event == "COMBAT_LOG_EVENT_UNFILTERED") then
		local timestamp, type, _, sourceGUID, sourceName, srcFlags, _, destGUID, destName, dstFlags = select(1, ...)
		if type == cd.cooldown['succ'] and bit.band(srcFlags, group) ~= 0 then
			local spellId, spellName, spellSchool = select(12, ...)
			if (spellId == cd.cooldown['spellID'] or (cd.cooldown.altSpellID and cd.cooldown.altSpellID[spellId])) then
				if spellId == 126393 or spellId == 90355 then -- find pet owner for Eternal Guardian and Ancient Hysteria (grumble grumble)
					local source, srcGUID = getPetOwner(source, srcGUID)
				end
				
				if cd.roster and not cd.roster[sourceName]  then
					debugPrint("spell ("..cd.cooldown.name..") casted but sourcename ("..sourceName..") is unknown",2)
				end
				
				if cd.roster and cd.roster[sourceName] and cd.roster[sourceName].dead  then
					debugPrint("spell ("..cd.cooldown.name..") casted but sourcename ("..sourceName..") is dead/disc !",2)
          BLTRCD.ShowBackMember(sourceName)
				end

				local txt=spellName.." ("..sourceName..") START"
				if (destName) then
					txt=txt.." on "..destName
				end

				local chan
				
				if cd.cooldown.startCDannounce == "inherit" then
					if BLTRCD.db.profile.display.category[cd.cooldown.category].startCDannounce == "inherit" then
						chan = BLTRCD.db.profile.startCDannounce
					else
						chan = BLTRCD.db.profile.display.category[cd.cooldown.category].startCDannounce
					end
				else
					chan = cd.cooldown.startCDannounce
				end
				BLTRCD.announce(txt, chan)
				
				BLTRCD.StartCD(cd, sourceName)
				BLTRCD.DisplayCD()
				
				if cd.cooldown.d_enabled == "yes" 
					or (cd.cooldown.d_enabled == "inherit" and BLTRCD.db.profile.display.category[cd.cooldown.category].d_enabled == "yes")
					or (cd.cooldown.d_enabled == "inherit" 
						and BLTRCD.db.profile.display.category[cd.cooldown.category].d_enabled == "inherit"
						and BLTRCD.db.profile.d_enabled)
					then
					BLTRCD.StartActiveCD(cd, sourceName)
					BLTRCD.RearrangeActiveCD()
				end
			end
		elseif type == "UNIT_DIED" then
			if bit.band(dstFlags, COMBATLOG_OBJECT_TYPE_PLAYER) ~= 0 and bit.band(dstFlags, group) ~= 0 then
				debugPrint("RAID MEMBER DIED : "..destName,2)
        BLTRCD.HideMemberCD(destName, cd)
        BLTRCD.DisplayCD()
			elseif bit.band(dstFlags, group) ~= 0 then
				debugPrint("RAID TRUC DIED : "..destName,2)
			else
				debugPrint("UNIT DIED : "..destName,2)
			end
		end
	end	
end

function BLTRCD.announce(msg,chan)
	if chan == "no" then
		return
	elseif chan == "officer" then
		SendChatMessage(msg ,"OFFICER")	
	elseif chan == "rw" and (UnitIsGroupLeader("player") or UnitIsRaidOfficer("player")) then
		SendChatMessage(msg ,"RAID_WARNING")
	elseif (chan == "raid" or chan == "rw") and (BLTRCD.GetPartyType()=="raid" or BLTRCD.GetPartyType()=="party" or BLTRCD.GetPartyType()=="lfr") then
		local targetchan=BLTRCD.GetPartyType()
		if targetchan=="raid" then
			SendChatMessage(msg ,"RAID")
		elseif targetchan=="party" then
			SendChatMessage(msg ,"PARTY")
		elseif targetchan=="lfr" then
			SendChatMessage(msg ,"INSTANCE_CHAT")
		else 
			debugPrint("BLTRCD.announce : Unknown group type", 2)
		end
	elseif (chan == "raid" or chan == "rw" or chan == "say") then
		SendChatMessage(msg ,"SAY")
	else 
		print(msg)
	end
end

function BLTRCD.ListAOEHealCD()
  SendChatMessage("List of Raid defensive CD" ,"OFFICER")	
  for _,cd in pairs(BLTRCD.categories["AOE_HEAL"].cdlist) do
    if cd.nbCD > 0 then
      local msg=" - "..cd.cooldown.real_name.." x "..cd.nbCD.." ("
      for name,x in pairs(cd.roster) do 
        msg=msg..name.." "
      end
      msg=msg..")"
      SendChatMessage(msg ,"OFFICER")	
    end
  end
end

function BLTRCD.ListAOEDPSCD()
  SendChatMessage("List of Raid offensive CD" ,"OFFICER")	
  for _,cd in pairs(BLTRCD.categories["AOE_DPS"].cdlist) do
    if cd.nbCD > 0 then
      local msg=" - "..cd.cooldown.real_name.." x "..cd.nbCD.." ("
      for name,x in pairs(cd.roster) do 
        msg=msg..name.." "
      end
      msg=msg..")"
      SendChatMessage(msg ,"OFFICER")	
    end
  end
end
